package models

import (
	"errors"
	//"fmt"

	"fmt"
	"log"
	"time"

	//"strconv"

	"github.com/beego/beego/v2/client/orm"
	"github.com/beego/beego/v2/core/validation"
)

type Xf_waf_rule struct {
	Id         int64  `json:"id"`
	Appname    string `json:"appname" valid:"Required"`
	Ruletype   string `json:"ruletype" valid:"Required"`
	Ruleitem   string `json:"ruleitem" valid:"Required"`
	Enable     bool   `json:"enable"`
	Remarks    string `json:"remarks"`
	Updatetime string `json:"updatetime"`
	Createtime string `json:"createtime"`
}

func init() {
	orm.Debug = true
	orm.RegisterModel(new(Xf_waf_rule))
}

func check(u *Xf_waf_rule) (err error) {
	valid := validation.Validation{}
	b, _ := valid.Valid(&u)
	if !b {
		for _, err := range valid.Errors {
			log.Println(err.Key, err.Message)
			return errors.New(err.Message)
		}
	}
	return nil
}

//List
//func GetXf_waf_ruleList(appname, ruletype string, id int64) (xf_waf_rule []orm.Params, count int64) {
func GetXf_waf_ruleList(appname, ruletype string, id, page, page_size int64) (xfr []Xf_waf_rule, count int64) {
	o := orm.NewOrm()
	qs := o.QueryTable(new(Xf_waf_rule))
	cond := orm.NewCondition()
	var offset int64
	if page <= 1 {
		offset = 0
	} else {
		offset = (page - 1) * page_size
	}
	if id > 0 {
		cond = cond.And("id", id)
	}
	if appname != "" {
		//cond = cond.And("appname", appname).OrCond(cond.Or("appname", "sys"))
		cond = cond.OrCond(cond.And("appname", appname).Or("appname", "sys"))
	}
	if ruletype != "" {
		if ruletype != "cfg" {
			cond = cond.And("ruletype", ruletype)
		}
	}

	qs = qs.SetCond(cond)
	if ruletype == "cfg" {
		qs.Limit(page_size, offset).OrderBy("-id").All(&xfr, "Id", "Appname", "Ruletype", "Ruleitem", "Enable", "Updatetime")
	} else {
		qs.Limit(page_size, offset).OrderBy("-id").All(&xfr)
	}
	//qs.All(&xfr)
	count, _ = qs.Count()
	return xfr, count
}

//for api
func GetRuleList(appname string) (xfr []Xf_waf_rule, count int64) {
	o := orm.NewOrm()
	qs := o.QueryTable(new(Xf_waf_rule))
	cond := orm.NewCondition()
	if appname != "" {
		//cond = cond.And("appname", appname).OrCond(cond.Or("appname", "sys"))
		cond = cond.OrCond(cond.And("appname", appname).Or("appname", "sys"))
	}
	qs = qs.SetCond(cond)
	qs.OrderBy("-id").All(&xfr, "Id", "Appname", "Ruletype", "Ruleitem", "Enable", "Updatetime")
	count, _ = qs.Count()
	return xfr, count
}

//添加
func AddXf_waf_rule(u *Xf_waf_rule) (int64, error) {
	if err := check(u); err != nil {
		return 0, err
	}
	o := orm.NewOrm()
	Xf_waf_rule := new(Xf_waf_rule)
	Xf_waf_rule.Appname = u.Appname
	Xf_waf_rule.Ruletype = u.Ruletype
	Xf_waf_rule.Ruleitem = u.Ruleitem
	//Xf_waf_rule.Enable = true
	Xf_waf_rule.Remarks = u.Remarks
	Xf_waf_rule.Createtime = time.Now().Format("2006-01-02 15:04:05")
	Xf_waf_rule.Updatetime = time.Now().Format("2006-01-02 15:04:05")
	id, err := o.Insert(Xf_waf_rule)
	UpdateConfigTime(u.Appname)
	return id, err
}

//创建应用时批量插入规则
func InsertWafRule(appname string) (int64, error) {
	o := orm.NewOrm()
	//[Err] 1055 - Expression #1 of ORDER BY clause is not in GROUP BY clause and contains nonaggregated column 'information_schema.PROFILING.SEQ' which is not functionally dependent on columns in GROUP BY clause; this is incompatible with sql_mode=only_full_group_by
	sqlstr := fmt.Sprintf("INSERT INTO xf_waf_rule(appname,ruletype,ruleitem,enable,remarks) SELECT '%s',ruletype,ruleitem,enable,remarks FROM xf_waf_rule WHERE appname = 'default'", appname)
	res, err := o.Raw(sqlstr).Exec()
	if err == nil {
		num, _ := res.RowsAffected()
		log.Println("[INFO] InsertRule affected nums: ", num)
		return num, nil
	}
	return 0, err
}

// //更新
func UpdateXf_waf_rule(u *Xf_waf_rule) (int64, error) {
	if err := check(u); err != nil {
		return 0, err
	}
	o := orm.NewOrm()
	op := make(orm.Params)

	if u.Id > 0 {
		op["Id"] = u.Id
	}

	if len(u.Appname) > 0 {
		op["Appname"] = u.Appname
	}
	if len(u.Ruletype) > 0 {
		op["Ruletype"] = u.Ruletype
	}
	if len(u.Ruleitem) > 0 {
		op["Ruleitem"] = u.Ruleitem
	}
	if len(u.Remarks) > 0 {
		op["Remarks"] = u.Remarks
	}
	//op["Updatetime"] = time.Now().Format("2006-01-02 15:04:05")
	if len(op) == 0 {
		return 0, errors.New("update field is empty")
	}
	var table Xf_waf_rule
	num, err := o.QueryTable(table).Filter("Id", u.Id).Update(op)
	UpdateConfigTime(u.Appname)
	return num, err
}

func DelByRuleId(id int64, appname string) (int64, error) {
	o := orm.NewOrm()
	status, err := o.Delete(&Xf_waf_rule{Id: id})
	if err == nil {
		UpdateConfigTime(appname)
	}
	return status, err
}

func EditRule(id, appname, key, value string) (int64, error) {
	o := orm.NewOrm()
	sqlstr := fmt.Sprintf("UPDATE xf_waf_rule SET %s = '%s' WHERE  id = %s AND appname = '%s'", key, value, id, appname)
	res, err := o.Raw(sqlstr).Exec()
	if err == nil {
		num, _ := res.RowsAffected()
		log.Printf("[INFO] EditRule affected nums:%d\n", num)
		UpdateConfigTime(appname)
		return num, nil
	}
	return 0, err
}
